﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Vra.DataAccess.Misc;

namespace Vra.DataAccess
{
	public class CommonDao<T> : BaseDao, IBaseDao<T> where T : class, new()
	{
		public virtual T Get(T item)
		{
			//Получаем объект подключения к базе
			using (var conn = GetConnection())
			{
				//Открываем соединение
				conn.Open();
				//Создаем sql команду
				using (var cmd = conn.CreateCommand())
				{
					//Задаём текст команды
					cmd.CommandText = QueryManager.GetSelectQuery<T>(LoadIdentityValue(item));
					LoadParameters(cmd, QueryType.SelectById, item);
					//Добавляем значение параметра
					//cmd.Parameters.AddWithValue("@id", id);
					//Открываем SqlDataReader для чтения полученных в результате
					// выполнения запроса данных
					using (var dataReader = cmd.ExecuteReader())
					{
						return !dataReader.Read() ? null : LoadItem(dataReader);
					}
				}
			}
		}

		public virtual IList<T> GetAll()
		{
			IList<T> items = new List<T>();
			using (var conn = GetConnection())
			{
				conn.Open();
				using (var cmd = conn.CreateCommand())
				{
					cmd.CommandText = QueryManager.GetSelectQuery<T>();
					using (var dataReader = cmd.ExecuteReader())
					{
						while (dataReader.Read())
						{
							items.Add(LoadItem(dataReader));
						}
					}
				}
			}
			return items;
		}

		public virtual void Add(T item)
		{
			using (var conn = GetConnection())
			{
				conn.Open();
				using (var cmd = conn.CreateCommand())
				{
					cmd.CommandText = QueryManager.GetInsertQuery<T>();
					LoadParameters(cmd, QueryType.Insert, item);
					cmd.ExecuteNonQuery();
				}
			}
		}

		public virtual void Update(T item)
		{
			using (var conn = GetConnection())
			{
				conn.Open();
				using (var cmd = conn.CreateCommand())
				{
					cmd.CommandText = QueryManager.GetUpdateQuery<T>();
					LoadParameters(cmd, QueryType.Update, item);
					cmd.ExecuteNonQuery();
				}
			}
		}

		public virtual void Delete(T item)
		{
			using (var conn = GetConnection())
			{
				conn.Open();
				using (var cmd = conn.CreateCommand())
				{
					cmd.CommandText = QueryManager.GetDelQuery<T>();
					LoadParameters(cmd, QueryType.Delete, item);
					try
					{
						cmd.ExecuteNonQuery();
					}
					catch (Exception ex)
					{
						MessageBox.Show("Исключение базы данных: " + ex.ToString(), "WARNING!");
					}
				}
			}
		}

		protected virtual void LoadParameters<T>(SqlCommand cmd, QueryType type, T param) where T : class
		{
			if (cmd == null || param == null)
				return;
			IDictionary<string, string> columns = QueryManager.GetColumnsWithParams<T>(type);
			var fields = typeof (T).GetFields();
			foreach (var column in columns.Keys)
			{
				var paramName = columns[column];
				var field = fields.First(p => p.Name == column);
				object value = field.GetValue(param) ?? DBNull.Value;
				cmd.Parameters.AddWithValue(paramName, value);
			}
		}

		protected virtual T LoadItem(SqlDataReader reader)
		{
			return MiscUtils.Get<T>(reader);
		}
	}
}
